﻿using System.Security.Cryptography;
using System.Text;

namespace AESLib
{
    public static class AESProvider
    {

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="key16">16字节密钥（会自动修正）</param>
        /// <param name="iv16">16字节iv（会自动修正）</param>
        /// <returns></returns>
        public static byte[] Enc(byte[] data, string key16, string iv16)
        {
            using Aes aes = Aes.Create();

            aes.Key = fix16(key16);
            aes.IV = fix16(iv16);

            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

            MemoryStream stream = new MemoryStream();
            CryptoStream cs = new CryptoStream(stream, encryptor, CryptoStreamMode.Write);
            cs.Write(data);
            cs.Flush();
            cs.FlushFinalBlock();
            stream.Flush();

            byte[] enc = stream.ToArray();
            return enc;
        }

        /// <summary>
        /// 加密并以base64字符串返回
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key16"></param>
        /// <param name="iv16"></param>
        /// <returns></returns>
        public static string EncToBase64(byte[] data, string key16, string iv16)
            => Convert.ToBase64String(Enc(data, key16, iv16));



        /// <summary>
        /// 解密 
        /// </summary>
        /// <param name="encData">加密数据</param>
        /// <param name="key16">16字节密钥（会自动修正）</param>
        /// <param name="iv16">16字节iv（会自动修正）</param>
        /// <returns></returns>
        public static byte[] Dec(byte[] encData, string key16, string iv16)
        {
            Aes aes = Aes.Create();

            aes.Key = fix16(key16);
            aes.IV = fix16(iv16);

            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);

            MemoryStream stream = new MemoryStream(encData);
            CryptoStream cs = new CryptoStream(stream, decryptor, CryptoStreamMode.Read);

            //这里必需用循环读取
            List<byte> ret = new();
            byte[] buf = new byte[1024];

            int r = cs.Read(buf, 0, 1024);
            while (r > 0)
            {
                ret.AddRange(buf.Take(r));
                r = cs.Read(buf, 0, 1024);
            }

            return ret.ToArray();
        }


        /// <summary>
        /// 解密以Base64编码的数据
        /// </summary>
        /// <param name="dataBase64"></param>
        /// <param name="key16"></param>
        /// <param name="iv16"></param>
        /// <returns></returns>
        public static byte[] DecFromBase64(string dataBase64, string key16, string iv16)
            => Dec(Convert.FromBase64String(dataBase64), key16, iv16);



        /// <summary>
        /// 修正key/iv到16字节
        /// </summary>
        /// <param name="k"></param>
        /// <returns></returns>
        static byte[] fix16(string k)
        {
            int len = 16;

            byte[] key = Encoding.UTF8.GetBytes(k);
            if (key.Length == len) return key;

            if (key.Length > len) return key.Take(len).ToArray();

            else  //小于len,补0
            {
                byte[] fix = new byte[len - key.Length];
                return key.Concat(fix).ToArray();
            }
        }



    }


}

